package com.alit.face.koala.websocket;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.RemoteEndpoint.Basic;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alit.face.koala.app.data.E3JoinResponse;
import com.alit.face.koala.app.data.E3OpenResponse;

import lombok.extern.slf4j.Slf4j;

@ServerEndpoint(value = "/socket.io/")
@Component
@Slf4j
public class SocketIO {
  //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
  private static int onlineCount = 0;
  private Boolean debug = true;

  // concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
  private static CopyOnWriteArraySet<SocketIO> webSocketSet = new CopyOnWriteArraySet<SocketIO>();

  // 与某个客户端的连接会话，需要通过它来给客户端发送数据
  private Session session;

  /**
  * 连接建立成功调用的方法
  */
  @OnOpen
  public void onOpen(Session session) throws IOException {
    if (debug) {
      Map<String, String> map = session.getPathParameters();
      log.info("session.getPathParameters()" + map.toString());

      String str = session.getQueryString();
      log.info("session.getQueryString()" + str);

      String uri = session.getRequestURI().toString();
      log.info("session.getRequestURI().toString()" + uri);
    }
    this.session = session;
    webSocketSet.add(this); // 加入set中
    addOnlineCount(); // 在线数加1

    //构造返回值并返回
    E3OpenResponse response = new E3OpenResponse();
    response.setPingInterval(25000);
    response.setPingTimeout(240000);
    response.setSid("6eed8ddcfa1b4b07a9a8f2fdc1291b7a");
    response.setUpgrades(new ArrayList<String>());

    String jsonString = JSON.toJSONString(response);
    session.getBasicRemote().sendText("0" + jsonString);
  }

  /**
  * 连接关闭调用的方法
  */
  @OnClose
  public void onClose() {
    webSocketSet.remove(this); // 从set中删除
    subOnlineCount(); // 在线数减1
    System.out.println("有一连接关闭！当前在线人数为" + getOnlineCount());
  }

  /**
  * 收到客户端消息后调用的方法
  * @param message
  * 客户端发送过来的消息
  */
  @OnMessage
  public void onMessage(String message, Session session) {
    //log.info("来自客户端的消息:" + message);
    Basic remote = session.getBasicRemote();
    if (message.startsWith("40/warn/,")) {
      try {
        remote.sendText("40");
        remote.sendText("40/warn/");
      } catch (IOException e) {
        e.printStackTrace();
      }
    } else if (message.startsWith("42/warn/,")) {
      E3JoinResponse response = new E3JoinResponse();
      response.setSubject_type(-1);
      response.setWarn_num("0");
      response.setWarn_num_stranger("0");
      response.setWarn_num_stranger("0");
      response.setPhoto("");
      response.setSuccess(true);
      JSONArray jsonArray = new JSONArray();
      jsonArray.add("join");
      jsonArray.add(response);
      String array = jsonArray.toJSONString();
      message = "42/warn/," + array;

      try {
        remote.sendText(message);
      } catch (IOException e) {
        e.printStackTrace();
      }
    } else if (message.startsWith("2")) {
      try {
        remote.sendText("3");
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  /**
  * 发生错误时调用
  */
  @OnError
  public void onError(Session session, Throwable error) {
    System.out.println("发生错误");
    error.printStackTrace();
  }

  public void sendMessage(String message) throws IOException {
    this.session.getBasicRemote().sendText(message);

  }

  /**
  * 群发自定义消息
  */
  public static void sendInfo(String message) throws IOException {
    for (SocketIO item : webSocketSet) {
      try {
        item.sendMessage(message);
      } catch (IOException e) {
        continue;
      }
    }
  }

  public static synchronized int getOnlineCount() {
    return onlineCount;
  }

  public static synchronized void addOnlineCount() {
    onlineCount++;
  }

  public static synchronized void subOnlineCount() {
    onlineCount--;
  }

}
